﻿Function.RegisterNamespace("Test.System.Web.Event");

[Import("../../../../../Source/System.js.Web/System/Web/Event/01.IEventStrategy.js")]
[Import("../../../../../Source/System.js.Web/System/Web/Event/Strategies/EventStrategy.Legacy.js")]
[Import("../../../../../Source/System.js.Web/System/Web/Event/Strategies/EventStrategy.Redmond.js")]
[Import("../../../../../Source/System.js.Web/System/Web/Event/Strategies/EventStrategy.Standard.js")]
[Import("../../../../../Source/System.js.Web/System/Web/Event/EventManager.js")]
[Fixture]
Test.System.Web.Event.EventManager=function(){
    [Fixture]
    function EventManager(){
        [Fact]
        function CreatesStrategyManager(){
            var targetStrategyManager=System.Script.Strategy.StrategyManager;
            System.Script.Strategy.StrategyManager=function(){
                actual=true;
            }
            var actual=false;
            
            new System.Web.Event.EventManager();
            System.Script.Strategy.StrategyManager=targetStrategyManager;
        
            Assert.True(actual);
        }

        [Fact]
        function AssignsStrategyManagerToStrategies(){
            var targetStrategyManager=System.Script.Strategy.StrategyManager;
            System.Script.Strategy.StrategyManager=function(){
                expected=this;
            }
            var expected=null;
            var target=new System.Web.Event.EventManager();

            var actual=target.Strategies;
            System.Script.Strategy.StrategyManager=targetStrategyManager;
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function PassesStandardStrategyToStrategyManager(){
            var targetStrategyManager=System.Script.Strategy.StrategyManager;
            System.Script.Strategy.StrategyManager=function(targetStrategy){
                actual=targetStrategy;
            }
            var expected=System.Web.EventStrategy.Standard;
            var actual=null;
            
            new System.Web.Event.EventManager();
            System.Script.Strategy.StrategyManager=targetStrategyManager;
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function PassesRedmondStrategyToStrategyManager(){
            var targetStrategyManager=System.Script.Strategy.StrategyManager;
            System.Script.Strategy.StrategyManager=function(standardStrategy,targetStrategy){
                actual=targetStrategy;
            }
            var expected=System.Web.EventStrategy.Redmond;
            var actual=null;
            
            new System.Web.Event.EventManager();
            System.Script.Strategy.StrategyManager=targetStrategyManager;
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function PassesLegacyStrategyToStrategyManager(){
            var targetStrategyManager=System.Script.Strategy.StrategyManager;
            System.Script.Strategy.StrategyManager=function(standardStrategy,redmondStrategy,targetStrategy){
                actual=targetStrategy;
            }
            var expected=System.Web.EventStrategy.Legacy;
            var actual=null;
            
            new System.Web.Event.EventManager();
            System.Script.Strategy.StrategyManager=targetStrategyManager;
        
            Assert.Equal(expected,actual);
        }
    }
    
    [Fixture]
    function Dispose(){
        [Fact]
        function ClearsStoredEvents(){
            var target=new System.Web.Event.EventManager();
            target.Clear=function(){
                actual=true;
            }
            var actual=false;
            
            target.Dispose();
        
            Assert.True(actual);
        }
        
        [Fact]
        function ClearsStrategyManager(){
            var target=new System.Web.Event.EventManager();
            var targetClear=target.Strategies.Clear;
            target.Strategies.Clear=function(){
                actual=true;
                targetClear.apply(target,arguments);
            }
            var actual=false;
            
            target.Dispose();
            
            Assert.True(actual);
        }
        
        [Fact]
        function ReleasesReferenceToStrategyManager(){
            var target=new System.Web.Event.EventManager();
            
            target.Dispose();
            var actual=target.Strategies;
            
            Assert.Null(actual);
        }
    }
    
    [Fixture]
    function Add(){
        [Fact]
        function ThrowsIfNodeIsOmitted(){
            var targetMethod="Add";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Add();
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfNodeIsUndefined(){
            var targetMethod="Add";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Add(undefined);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfNodeIsNull(){
            var targetMethod="Add";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Add(null);
            });
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function DoesNotThrowIfNodeIsAnObject(){
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);

            var actual=Record.Exception(function(){
                target.Add({},"type",function(){});
            });
        
            Assert.Null(actual);
        }

        [Fact]
        function ThrowsIfTypeIsOmitted(){
            var targetMethod="Add";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Add({});
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeIsUndefined(){
            var targetMethod="Add";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Add({},undefined);
            });
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfTypeIsNull(){
            var targetMethod="Add";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Add({},null);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeDoesNotImplementToString(){
            var targetMethod="Add";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Add({},{toString:null});
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function DoesNotThrowIfTypeIsString(){
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
        
            var actual=Record.Exception(function(){
                target.Add({},"",function(){});
            });
        
            Assert.Null(actual);
        }
        
        [Fact]
        function DoesNotThrowIfTypeIsConvertibleToString(){
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
        
            var actual=Record.Exception(function(){
                target.Add({},{},function(){});
            });
        
            Assert.Null(actual);
        }

        [Fact]
        function ThrowsIfHandlerIsOmitted(){
            var targetMethod="Add";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'handler' must be a valid Function pointer.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Add({},"");
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfHandlerIsUndefined(){
            var targetMethod="Add";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'handler' must be a valid Function pointer.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Add({},"",undefined);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfHandlerIsNull(){
            var targetMethod="Add";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'handler' must be a valid Function pointer.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Add({},"",null);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfHandlerIsNotAFunction(){
            var targetMethod="Add";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'handler' must be a valid Function pointer.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Add({},"",{});
            });
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function DoesNotThrowIfHandlerIsAFunction(){
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
        
            var actual=Record.Exception(function(){
                target.Add({},"",function(){});
            });
        
            Assert.Null(actual);
        }
        
        [Fact]
        function AddsHandlerToTypeCollectionForNode(){
            var targetNode={};
            var targetType="target";
            var targetHandler=function(){};
            var target=new System.Web.Event.EventManager();
            var expected=[targetHandler];
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);

            target.Add(targetNode,targetType,targetHandler);
            var actual=target.Get(targetNode,targetType);
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function AddsMultipleHandlersToTypeCollectionForNode(){
            var targetNode={};
            var targetType="target";
            var target=new System.Web.Event.EventManager();
            var expected=[function handlerOne(){},function handlerTwo(){}];
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);

            target.Add(targetNode,targetType,expected[0]);
            target.Add(targetNode,targetType,expected[1]);
            var actual=target.Get(targetNode,targetType);
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function GetsStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            var targetGet=target.Strategies.Get;
            target.Strategies.Get=function(targetCandidate){
                actual=true;
                return targetGet(targetCandidate);
            };
            var actual=false;
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            
            target.Add({},"",function(){});
            
            Assert.True(actual);
        }

        [Fact]
        function PassesEnvironmentToGetStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            var targetGet=target.Strategies.Get;
            target.Strategies.Get=function(targetCandidate){
                actual=targetCandidate;
                return targetGet(targetCandidate);
            };
            var expected=Object.Global();
            var actual=null;
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            
            target.Add({},"",function(){});
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CallsAddOnStrategy(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Add:function(){
                    actual=true;
                }}
            }
            var actual=false;

            target.Add({},"",function(){});

            Assert.True(actual);            
        }

        [Fact]
        function PassesNodeToStrategyAdd(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Add:function(targetNode){
                    actual=targetNode;
                }}
            }
            var expected={};
            var actual=null;

            target.Add(expected,"",function(){});

            Assert.Same(expected,actual);            
        }

        [Fact]
        function PassesTypeToStrategyAdd(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Add:function(node,targetType){
                    actual=targetType;
                }}
            }
            var expected="";
            var actual=null;

            target.Add({},expected,function(){});

            Assert.Same(expected,actual);            
        }

        [Fact]
        function PassesHandlerToStrategyAdd(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Add:function(node,type,targetHandler){
                    actual=targetHandler;
                }}
            }
            var expected=function(){};
            var actual=null;

            target.Add({},"",expected);

            Assert.Same(expected,actual);            
        }
    }
    
    [Fixture]
    function Clear(){
        [Fact]
        function GetsStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.Remove=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add({},"",function(){});
            var targetGet=target.Strategies.Get;
            target.Strategies.Get=function(targetCandidate){
                actual=true;
                return targetGet(targetCandidate);
            };
            var actual=false;
            
            target.Clear();
            
            Assert.True(actual);
        }

        [Fact]
        function PassesEnvironmentToGetStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.Remove=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add({},"",function(){});
            var targetGet=target.Strategies.Get;
            target.Strategies.Get=function(targetCandidate){
                actual=targetCandidate;
                return targetGet(targetCandidate);
            };
            var expected=Object.Global();
            var actual=null;
            
            target.Clear();
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CallsRemoveOnStrategy(){
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.Remove=function(){actual=true;};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add({},"",function(){});
            var actual=false;

            target.Clear();

            Assert.True(actual);            
        }

        [Fact]
        function PassesNodeToStrategyRemove(){
            var target=new System.Web.Event.EventManager();
            var expected={};
            var voidStrategy=function(){
                this.Add=function(){};
                this.Remove=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(expected,"",function(){});
            target.Strategies.Get=function(){
                return {Remove:function(targetNode){
                    actual=targetNode;
                }}
            }
            var actual=null;

            target.Clear();

            Assert.Same(expected,actual);            
        }

        [Fact]
        function PassesTypeToStrategyRemove(){
            var target=new System.Web.Event.EventManager();
            var expected="";
            var voidStrategy=function(){
                this.Add=function(){};
                this.Remove=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add({},expected,function(){});
            target.Strategies.Get=function(){
                return {Remove:function(node,targetType){
                    actual=targetType;
                }}
            }
            var actual=null;

            target.Clear();

            Assert.Same(expected,actual);            
        }

        [Fact]
        function PassesHandlerToStrategyRemove(){
            var target=new System.Web.Event.EventManager();
            var expected=function(){};
            var voidStrategy=function(){
                this.Add=function(){};
                this.Remove=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add({},"",expected);
            target.Strategies.Get=function(){
                return {Remove:function(node,type,targetHandler){
                    actual=targetHandler;
                }}
            }
            var actual=null;

            target.Clear();

            Assert.Same(expected,actual);            
        }
        
        [Fact]
        function RemovesHandlerFromNodeTypeCollection(){
            var targetNode={};
            var targetType="target";
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.Remove=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(targetNode,targetType,function(){});

            target.Clear();
            var actual=target.Get(targetNode,targetType);
            
            Assert.Empty(actual);
        }

        [Fact]
        function RemovesAllHandlersFromNodeTypeCollection(){
            var targetNode={};
            var targetType="target";
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.Remove=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(targetNode,targetType,function handlerOne(){});
            target.Add(targetNode,targetType,function handlerTwo(){});

            target.Clear();
            var actual=target.Get(targetNode,targetType);
            
            Assert.Empty(actual);
        }
    }
    
    [Fixture]
    function Fire(){
        [Fact]
        function ThrowsIfNodeIsOmitted(){
            var targetMethod="Fire";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Fire();
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfNodeIsUndefined(){
            var targetMethod="Fire";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Fire(undefined);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfNodeIsNull(){
            var targetMethod="Fire";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Fire(null);
            });
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function DoesNotThrowIfNodeIsAnObject(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Fire:function(){}};
            };
        
            var actual=Record.Exception(function(){
                target.Fire({},"type");
            });
        
            Assert.Null(actual);
        }

        [Fact]
        function ThrowsIfTypeIsOmitted(){
            var targetMethod="Fire";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Fire({});
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeIsUndefined(){
            var targetMethod="Fire";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Fire({},undefined);
            });
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfTypeIsNull(){
            var targetMethod="Fire";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Fire({},null);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeDoesNotImplementToString(){
            var targetMethod="Fire";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Fire({},{toString:null});
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function DoesNotThrowIfTypeIsString(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Fire:function(){}};
            };
        
            var actual=Record.Exception(function(){
                target.Fire({},"");
            });
        
            Assert.Null(actual);
        }
        
        [Fact]
        function DoesNotThrowIfTypeIsConvertibleToString(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Fire:function(){}};
            };
       
            var actual=Record.Exception(function(){
                target.Fire({},{},function(){});
            });
        
            Assert.Null(actual);
        }
        
        [Fact]
        function GetsStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(targetCandidate){
                actual=true;
                return {Fire:function(){}};
            };
            var actual=false;
            
            target.Fire({},"",function(){});
            
            Assert.True(actual);
        }

        [Fact]
        function PassesEnvironmentToGetStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(targetCandidate){
                actual=targetCandidate;
                return {Fire:function(){}};
            };
            var expected=Object.Global();
            var actual=null;
            
            target.Fire({},"",function(){});
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CallsFireOnStrategy(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Fire:function(){
                    actual=true;
                }}
            }
            var actual=false;

            target.Fire({},"",function(){});

            Assert.True(actual);            
        }

        [Fact]
        function PassesNodeToStrategyFire(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Fire:function(targetNode){
                    actual=targetNode;
                }}
            }
            var expected={};
            var actual=null;

            target.Fire(expected,"");

            Assert.Same(expected,actual);            
        }

        [Fact]
        function PassesTypeToStrategyFire(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Fire:function(node,targetType){
                    actual=targetType;
                }}
            }
            var expected="";
            var actual=null;

            target.Fire({},expected);

            Assert.Same(expected,actual);            
        }

        [Fact]
        function PassesContextToStrategyFire(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Fire:function(node,type,targetContext){
                    actual=targetContext;
                }}
            }
            var expected={};
            var actual=null;

            target.Fire({},"",expected);

            Assert.Same(expected,actual);            
        }
    }
    
    [Fixture]
    function Get(){
        [Fact]
        function ThrowsIfNodeIsOmitted(){
            var targetMethod="Get";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Get();
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfNodeIsUndefined(){
            var targetMethod="Get";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Get(undefined);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfNodeIsNull(){
            var targetMethod="Get";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Get(null);
            });
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function DoesNotThrowIfNodeIsAnObject(){
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Get({},"type",function(){});
            });
        
            Assert.Null(actual);
        }

        [Fact]
        function ThrowsIfTypeIsOmitted(){
            var targetMethod="Get";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Get({});
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeIsUndefined(){
            var targetMethod="Get";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Get({},undefined);
            });
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfTypeIsNull(){
            var targetMethod="Get";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Get({},null);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeDoesNotImplementToString(){
            var targetMethod="Get";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Get({},{toString:null});
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function DoesNotThrowIfTypeIsString(){
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Get({},"",function(){});
            });
        
            Assert.Null(actual);
        }
        
        [Fact]
        function DoesNotThrowIfTypeIsConvertibleToString(){
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Get({},{},function(){});
            });
        
            Assert.Null(actual);
        }
        
        [Fact]
        function GetsHandlerFromTypeCollectionForNode(){
            var targetNode={};
            var targetType="target";
            var targetHandler=function(){};
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            var expected=[targetHandler];
            target.Add(targetNode,targetType,targetHandler);

            var actual=target.Get(targetNode,targetType);
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function GetsMultipleHandlersFromTypeCollectionForNode(){
            var targetNode={};
            var targetType="target";
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            var expected=[function handlerOne(){},function handlerTwo(){}];
            target.Add(targetNode,targetType,expected[0]);
            target.Add(targetNode,targetType,expected[1]);

            var actual=target.Get(targetNode,targetType);
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function DoesNotGetHandlersForUnknownNode(){
            var targetNode={};
            var targetType="target";
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(targetNode,targetType,function handlerOne(){});
            target.Add(targetNode,targetType,function handlerTwo(){});

            var actual=target.Get({},targetType);
            
            Assert.Empty(actual);
        }

        [Fact]
        function DoesNotGetHandlersForUnknownType(){
            var targetNode={};
            var targetType="target";
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(targetNode,targetType,function handlerOne(){});
            target.Add(targetNode,targetType,function handlerTwo(){});

            var actual=target.Get(targetNode,"unknown");
            
            Assert.Empty(actual);
        }
    }
    
    [Fixture]
    function Kill(){
        [Fact]
        function GetsStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(targetCandidate){
                actual=true;
                return {Kill:function(){}};
            };
            var actual=false;
            
            target.Kill();
            
            Assert.True(actual);
        }

        [Fact]
        function PassesEnvironmentToGetStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(targetCandidate){
                actual=targetCandidate;
                return {Kill:function(){}};
            };
            var expected=Object.Global();
            var actual=null;
            
            target.Kill();
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CallsKillOnStrategy(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Kill:function(){
                    actual=true;
                }}
            }
            var actual=false;

            target.Kill();

            Assert.True(actual);            
        }

        [Fact]
        function PassesEventToStrategyKill(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Kill:function(targetEvent){
                    actual=targetEvent;
                }}
            }
            var expected={};
            var actual=null;

            target.Kill(expected);

            Assert.Same(expected,actual);            
        }    
    }

    [Fixture]
    function Remove(){
        [Fact]
        function ThrowsIfNodeIsOmitted(){
            var targetMethod="Remove";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove();
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfNodeIsUndefined(){
            var targetMethod="Remove";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove(undefined);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfNodeIsNull(){
            var targetMethod="Remove";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'node' must be a valid Node.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove(null);
            });
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function DoesNotThrowIfNodeIsAnObject(){
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({},"type",function(){});
            });
        
            Assert.Null(actual);
        }

        [Fact]
        function ThrowsIfTypeIsOmitted(){
            var targetMethod="Remove";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({});
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeIsUndefined(){
            var targetMethod="Remove";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({},undefined);
            });
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfTypeIsNull(){
            var targetMethod="Remove";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({},null);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeDoesNotImplementToString(){
            var targetMethod="Remove";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'type' must be convertible to String.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({},{toString:null});
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function DoesNotThrowIfTypeIsString(){
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({},"",function(){});
            });
        
            Assert.Null(actual);
        }
        
        [Fact]
        function DoesNotThrowIfTypeIsConvertibleToString(){
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({},{},function(){});
            });
        
            Assert.Null(actual);
        }

        [Fact]
        function ThrowsIfHandlerIsOmitted(){
            var targetMethod="Remove";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'handler' must be a valid Function pointer.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({},"");
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfHandlerIsUndefined(){
            var targetMethod="Remove";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'handler' must be a valid Function pointer.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({},"",undefined);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfHandlerIsNull(){
            var targetMethod="Remove";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'handler' must be a valid Function pointer.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({},"",null);
            });
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfHandlerIsNotAFunction(){
            var targetMethod="Remove";
            var expected=String.Format("System.Web.Event.EventManager.{0}: 'handler' must be a valid Function pointer.",targetMethod);
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({},"",{});
            });
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function DoesNotThrowIfHandlerIsAFunction(){
            var target=new System.Web.Event.EventManager();
        
            var actual=Record.Exception(function(){
                target.Remove({},"",function(){});
            });
        
            Assert.Null(actual);
        }

        [Fact]
        function GetsStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            var targetNode={};
            var targetType="";
            var targetHandler=function(){};
            target.Add(targetNode,targetType,targetHandler);
            target.Strategies.Get=function(targetCandidate){
                actual=true;
                return {Remove:function(){}};
            };
            var actual=false;

            target.Remove(targetNode,targetType,targetHandler);
            
            Assert.True(actual);
        }

        [Fact]
        function PassesEnvironmentToGetStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            var targetNode={};
            var targetType="";
            var targetHandler=function(){};
            target.Add(targetNode,targetType,targetHandler);
            target.Strategies.Get=function(targetCandidate){
                actual=targetCandidate;
                return {Remove:function(){}};
            };
            var expected=Object.Global();
            var actual=null;
            
            target.Remove(targetNode,targetType,targetHandler);
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CallsRemoveOnStrategy(){
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            var targetNode={};
            var targetType="";
            var targetHandler=function(){};
            target.Add(targetNode,targetType,targetHandler);
            target.Strategies.Get=function(){
                return {Remove:function(){
                    actual=true;
                }}
            }
            var actual=false;

            target.Remove(targetNode,targetType,targetHandler);

            Assert.True(actual);            
        }

        [Fact]
        function PassesNodeToStrategyRemove(){
            var target=new System.Web.Event.EventManager();
            var expected={};
            var targetType="";
            var targetHandler=function(){};
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(expected,targetType,targetHandler);
            target.Strategies.Get=function(){
                return {Remove:function(targetNode){
                    actual=targetNode;
                }}
            }
            var actual=null;

            target.Remove(expected,targetType,targetHandler);

            Assert.Same(expected,actual);            
        }

        [Fact]
        function PassesTypeToStrategyRemove(){
            var target=new System.Web.Event.EventManager();
            var expected="";
            var targetNode={};
            var targetHandler=function(){};
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(targetNode,expected,targetHandler);
            target.Strategies.Get=function(){
                return {Remove:function(node,targetType){
                    actual=targetType;
                }}
            }
            var actual=null;

            target.Remove(targetNode,expected,targetHandler);

            Assert.Same(expected,actual);            
        }

        [Fact]
        function PassesHandlerToStrategyRemove(){
            var target=new System.Web.Event.EventManager();
            var expected=function(){};
            var targetNode={};
            var targetType="";
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(targetNode,targetType,expected);
            target.Strategies.Get=function(){
                return {Remove:function(node,type,targetHandler){
                    actual=targetHandler;
                }}
            }
            var actual=null;

            target.Remove(targetNode,targetType,expected);

            Assert.Same(expected,actual);            
        }
        
        [Fact]
        function RemovesHandlerFromNodeTypeCollection(){
            var targetNode={};
            var targetType="target";
            var targetHandler=function(){};
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.Remove=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(targetNode,targetType,targetHandler);

            target.Remove(targetNode,targetType,targetHandler);
            var actual=target.Get(targetNode,targetType);
            
            Assert.Empty(actual);
        }

        [Fact]
        function DoesnNotRemoveHandlerIfNodeDoesntMatch(){
            var targetNode={};
            var targetType="target";
            var targetHandler=function(){};
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(targetNode,targetType,targetHandler);

            target.Remove({},targetType,targetHandler);
            var actual=target.Get(targetNode,targetType);
            
            Assert.NotEmpty(actual);
        }

        [Fact]
        function DoesnNotRemoveHandlerIfTypeDoesntMatch(){
            var targetNode={};
            var targetType="target";
            var targetHandler=function(){};
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(targetNode,targetType,targetHandler);

            target.Remove(targetNode,"",targetHandler);
            var actual=target.Get(targetNode,targetType);
            
            Assert.NotEmpty(actual);
        }

        [Fact]
        function DoesnNotRemoveHandlerIfHandlerDoesntMatch(){
            var targetNode={};
            var targetType="target";
            var targetHandler=function(){};
            var target=new System.Web.Event.EventManager();
            var voidStrategy=function(){
                this.Add=function(){};
                this.IsSatisfiedBy=function(candidate){return true;}
            };
            target.Strategies.Add(voidStrategy,0);
            target.Add(targetNode,targetType,targetHandler);

            target.Remove(targetNode,targetType,function(){});
            var actual=target.Get(targetNode,targetType);
            
            Assert.NotEmpty(actual);
        }
   
    }

    [Fixture]
    function Suppress(){
        [Fact]
        function GetsStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(targetCandidate){
                actual=true;
                return {Suppress:function(){}};
            };
            var actual=false;
            
            target.Suppress();
            
            Assert.True(actual);
        }

        [Fact]
        function PassesEnvironmentToGetStrategyFromStrategyManager(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(targetCandidate){
                actual=targetCandidate;
                return {Suppress:function(){}};
            };
            var expected=Object.Global();
            var actual=null;
            
            target.Suppress();
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CallsSuppressOnStrategy(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Suppress:function(){
                    actual=true;
                }}
            }
            var actual=false;

            target.Suppress();

            Assert.True(actual);            
        }

        [Fact]
        function PassesEventToStrategySuppress(){
            var target=new System.Web.Event.EventManager();
            target.Strategies.Get=function(){
                return {Suppress:function(targetEvent){
                    actual=targetEvent;
                }}
            }
            var expected={};
            var actual=null;

            target.Suppress(expected);

            Assert.Same(expected,actual);            
        }    
    }

}